﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Devices.Radio;
using System.Windows.Media.Imaging;
using System.IO;
using Microsoft.Devices;
using System.Windows.Resources;
using Microsoft.Phone;
using System.ComponentModel;
using System.Threading;
using System.Collections.ObjectModel;
using Microsoft.Xna.Framework.Media;

namespace MRadio.Device
{
    public class Tuner
    {
        // Fields
        private double _frequency=100.0;
        private PropertyChangedEventHandler _propertyChanged;
        private FMRadio radio = FMRadio.Instance;
        private AutoResetEvent lockEvent = new AutoResetEvent(true);
        private bool _isBusy = false;

        private bool _ifAnyChannel = false;
        private bool _isGoMin = false;
        private bool _isGoMax = false;
        // Events
        public event PropertyChangedEventHandler PropertyChanged
        {
            add
            {
                PropertyChangedEventHandler handler2;
                PropertyChangedEventHandler propertyChanged = this._propertyChanged;
                do
                {
                    handler2 = propertyChanged;
                    PropertyChangedEventHandler handler3 = (PropertyChangedEventHandler)Delegate.Combine(handler2, value);
                    propertyChanged = Interlocked.CompareExchange<PropertyChangedEventHandler>(ref this._propertyChanged, handler3, handler2);
                }
                while (propertyChanged != handler2);
            }
            remove
            {
                PropertyChangedEventHandler handler2;
                PropertyChangedEventHandler propertyChanged = this._propertyChanged;
                do
                {
                    handler2 = propertyChanged;
                    PropertyChangedEventHandler handler3 = (PropertyChangedEventHandler)Delegate.Remove(handler2, value);
                    propertyChanged = Interlocked.CompareExchange<PropertyChangedEventHandler>(ref this._propertyChanged, handler3, handler2);
                }
                while (propertyChanged != handler2);
            }
        }

        public event EventHandler NoChannelEvent;
        // Methods
        public Tuner()
        {
            this._frequency = (double)this.Minimum;
            //this.Start();
        }

        //public ObservableCollection<StationViewModel> GetLocal()
        //{
        //    double frequency = this.Frequency;
        //    ObservableCollection<StationViewModel> observables = new ObservableCollection<StationViewModel>();
        //    List<StationViewModel> list = new List<StationViewModel>();
        //    if (!this.IsStopped())
        //    {
        //        do
        //        {
        //            this.Frequency += this.Increment;
        //            Thread.Sleep(TimeSpan.FromMilliseconds(50.0));
        //            if (this.IsTuned())
        //            {
        //                StationViewModel item = new StationViewModel();
        //                item.Frequency = this.Frequency;
        //                item.StationId = string.Empty;
        //                item.Category = "Unknown";
        //                list.Add(item);
        //            }
        //            if (this.Frequency == this.Maximum)
        //            {
        //                this.Frequency = this.Minimum;
        //                Thread.Sleep(TimeSpan.FromMilliseconds(50.0));
        //                if (this.IsTuned())
        //                {
        //                    StationViewModel model2 = new StationViewModel();
        //                    model2.Frequency = this.Frequency;
        //                    model2.StationId = string.Empty;
        //                    model2.Category = "Unknown";
        //                    list.Add(model2);
        //                }
        //            }
        //        }
        //        while (this.Frequency != frequency);
        //        list.Sort();
        //        foreach (StationViewModel model3 in list)
        //        {
        //            observables.Add(model3);
        //        }
        //    }
        //    return observables;
        //}

        public double GetNext()
        {
            if (this.Frequency == this.Maximum)
            {
                this.Frequency = this.Minimum;
            }
            else
            {
                this.Frequency += this.Increment;
            }
            return this.Frequency;
        }

        public double GetPrevious()
        {
            if (this.Frequency == this.Minimum)
            {
                this.Frequency = this.Maximum;
            }
            else
            {
                this.Frequency -= this.Increment;
            }
            return this.Frequency;
        }

        public bool IsStopped()
        {
            return (this.radio.PowerMode == RadioPowerMode.Off);
        }

        public bool IsTuned()
        {
            // System.Diagnostics.Debug.WriteLine(this.SignalStrength);

            return (this.SignalStrength >= 0.2);
        }

        private void NotifyPropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler propertyChanged = this._propertyChanged;
            if (propertyChanged != null)
            {
                //UpdateMediaHub();
                propertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }


        public double ScanNext()
        {
            if (!this.IsStopped()&& !_isBusy)
            {          
                ThreadPool.QueueUserWorkItem(new WaitCallback((o)=>{
                    ThreadScanNext();
                }));
            }
            return this.Frequency;
        }

        public double ScanPrevious()
        {
            if (!this.IsStopped() && !_isBusy)
            {
                ThreadPool.QueueUserWorkItem(new WaitCallback((o) =>
                {
                    ThreadScanPrevious();
                }));               
            }
            return this.Frequency;
        }
        /// <summary>
        /// the scan next method in other thread.
        /// </summary>
        /// <param name="frequency"></param>
        private void ThreadScanNext()
        {
            //if (!lockEvent.WaitOne(10))
            //    return;
            lockEvent.WaitOne();
            double frequency = this.Frequency;
            _isBusy = true;
            while (this.Frequency < this.Maximum)
            {
                this.Frequency = this.Frequency + this.Increment;
                if (this.Frequency == frequency)
                {
                    break;
                }
                Thread.Sleep(TimeSpan.FromMilliseconds(50.0));
                if (this.IsTuned())
                {
                    this.NotifyPropertyChanged("Frequency");
                    _ifAnyChannel = true;
                    break;
                }
                if (this.Frequency >= this.Maximum)
                {
                    _isGoMax = true;
                    break;
                }
            }
            _isBusy = false;
            RaiseNoHeadPhone();
            lockEvent.Set();
        }

        /// <summary>
        /// If no channel been found,then show the messagebox to info the user should insert headphone.
        /// </summary>
        private void RaiseNoHeadPhone()
        {
            if (_isGoMin && _isGoMin && !_ifAnyChannel)
            {
                if (NoChannelEvent != null)
                {
                    NoChannelEvent(this,null);
                }
                _isGoMin = false;
                _isGoMin = false;
                _ifAnyChannel = false;
            }
        }
      
        /// <summary>
        /// the scan previous method in other thread.
        /// </summary>
        /// <param name="frequency"></param>
        private void ThreadScanPrevious()
        {
            //if (!lockEvent.WaitOne(10))
            //    return;
            lockEvent.WaitOne();
            _isBusy = true;
            double frequency = this.Frequency;
            while (this.Frequency > this.Minimum)
            {
                this.Frequency = double.Parse(((float)this.Frequency - (float)this.Increment).ToString());
                if (this.Frequency == frequency)
                {
                    break;
                }
                Thread.Sleep(TimeSpan.FromMilliseconds(50.0));

                if (this.IsTuned())
                {
                    this.NotifyPropertyChanged("Frequency");
                    _ifAnyChannel = true;
                    break;
                }
                if (this.Frequency <= this.Minimum)
                {
                    _isGoMin = true;
                    break;
                }
            }
            _isBusy = false;
            RaiseNoHeadPhone();
            lockEvent.Set();
        }

        public void Start()
        {
            try
            {
                if (this.radio.PowerMode == RadioPowerMode.Off)
                {
                    this.radio.PowerMode = RadioPowerMode.On;
                    try
                    {
                        this.Frequency = this.radio.Frequency; //this.Frequency;
                    }
                    catch (Exception exception)
                    {
                        //MessageBox.Show(exception.Message, "Frequency Change (1)", MessageBoxButton.OK);
                    }
                }
            }
            catch (Exception exception2)
            {
                //MessageBox.Show(exception2.Message, "Radio Power On", MessageBoxButton.OK);
                //this.Stop();
                MediaPlayer.Pause();
            }
        }

        public void Stop()
        {
            try
            {
                if (this.radio.PowerMode == RadioPowerMode.On)
                {
                    this.radio.PowerMode = RadioPowerMode.Off;
                    MediaPlayer.Pause();
                }
            }
            catch (Exception)
            {
            }
        }

        public void StopMedia()
        {
            if (MediaPlayer.State == MediaState.Playing)
            {
                MediaPlayer.Stop();
            }
        }

        public void UpdateMediaHub()
        {
            try
            {
                StreamResourceInfo resourceStream = null;
                Uri uriResource = new Uri("Background.png", UriKind.Relative);
                resourceStream = Application.GetResourceStream(uriResource);
                PictureDecoder.DecodeJpeg(resourceStream.Stream);
                resourceStream.Stream.Seek(0L, SeekOrigin.Begin);
                MediaHistoryItem item2 = new MediaHistoryItem();
                //item2.Title = AppResources.portablefm;
                item2.Source = string.Empty;
                item2.ImageStream = resourceStream.Stream;
                MediaHistoryItem item = item2;
                item.PlayerContext.Add("RadioFrequencyKey", this.Frequency.ToString());
                MediaHistory.Instance.NowPlaying = item;
                resourceStream.Stream.Seek(0L, SeekOrigin.Begin);
                MediaHistory.Instance.WriteRecentPlay(item);
            }
            catch (Exception)
            {
            }
        }

        public void UpdateMediaHubCurrent(UIElement element)
        {
            try
            {
                WriteableBitmap bitmap = new WriteableBitmap(element, null);
                MemoryStream targetStream = new MemoryStream();
                bitmap.SaveJpeg(targetStream, 0xad, 0xad, 0, 90);
                targetStream.Seek(0L, SeekOrigin.Begin);
                MediaHistoryItem item = new MediaHistoryItem();
                // item.Title = AppResources.portablefm;
                item.Source = "";
                item.ImageStream = targetStream;
                item.PlayerContext.Add("RadioFrequencyKey", this.Frequency.ToString());
                MediaHistory.Instance.NowPlaying = item;
            }
            catch (Exception)
            {
            }
        }

        public void UpdateMediaHubHistory(UIElement element)
        {
            try
            {
                WriteableBitmap bitmap = new WriteableBitmap(element, null);
                MemoryStream targetStream = new MemoryStream();
                bitmap.SaveJpeg(targetStream, 0xad, 0xad, 0, 90);
                targetStream.Seek(0L, SeekOrigin.Begin);
                MediaHistoryItem item = new MediaHistoryItem();
                //item.Title = AppResources.portablefm;
                item.Source = "";
                item.ImageStream = targetStream;
                item.PlayerContext.Add("RadioFrequencyKey", this.Frequency.ToString());
                MediaHistory.Instance.NowPlaying = item;
                targetStream.Seek(0L, SeekOrigin.Begin);
                MediaHistory.Instance.WriteRecentPlay(item);
            }
            catch (Exception)
            {
            }
        }

        public void UpdateMediaHubNew(UIElement element)
        {
            try
            {
                WriteableBitmap bitmap = new WriteableBitmap(element, null);
                MemoryStream targetStream = new MemoryStream();
                bitmap.SaveJpeg(targetStream, 0xad, 0xad, 0, 90);
                targetStream.Seek(0L, SeekOrigin.Begin);
                MediaHistoryItem item = new MediaHistoryItem();
                //item.Title = AppResources.portablefm;
                item.Source = "";
                item.ImageStream = targetStream;
                item.PlayerContext.Add("RadioFrequencyKey", this.Frequency.ToString());
                MediaHistory.Instance.WriteAcquiredItem(item);
            }
            catch (Exception)
            {
            }
        }

        // Properties
        public double Frequency
        {
            get
            {
                return (double)this._frequency;
            }
            set
            {
                double num = double.Parse(value.ToString());
                if (num != this._frequency)
                {
                    try
                    {
                        if (this.radio.PowerMode == RadioPowerMode.On )
                            //&& num >= this.Minimum 
                            //&& num <=this.Maximum
                        {
                            this.radio.Frequency = (double)num;
                        }
                        this._frequency = num;
                        //this.NotifyPropertyChanged("Frequency");
                    }
                    catch (Exception e)
                    {
                        this._frequency = (double)this.Minimum;
                    }
                }
            }
        }

        public double Increment
        {
            get
            {
                if (this.radio.CurrentRegion == RadioRegion.UnitedStates)
                {
                    return 0.2;
                }
                return 0.1;
            }
        }

        public double Maximum
        {
            get
            {
                if (this.radio.CurrentRegion == RadioRegion.Japan)
                {
                    return 90.0;
                }
                return 107.9;
            }
        }

        public double Minimum
        {
            get
            {
                if (this.radio.CurrentRegion == RadioRegion.Japan)
                {
                    return 76.0;
                }
                return 87.9;
            }
        }

        public RadioRegion Region
        {
            get
            {
                return this.radio.CurrentRegion;
            }
            set
            {
                this.radio.CurrentRegion = value;
            }
        }

        public double SignalStrength
        {
            get
            {
                return this.radio.SignalStrength;
            }
        }
    }



}
